/*
* Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
* Description: image_mbuf_video_sender source file
*/
#include "image_mbuf_video_sender.h"

#define buffGrpName "DEFAULT_MEM_GROUP"

int32_t ImageMbufVideoSender::InitGrp(void)
{
    GroupShareAttr Mattr = {0};
    GroupCfg grpcfg = {0};
    BuffCfg buffcfg = {0};
    int32_t devId = 0;
    int32_t ret;
    grpcfg.maxMemSize = 1024 * 1024 * 32;
    Mattr.admin = 1;
    Mattr.alloc = 1;
    Mattr.write = 1;
    Mattr.read = 1;
    ret = halGrpAttach(buffGrpName, 0);
    if (ret != HI_SUCCESS) {
        printf("manager halGrpAttach failed! ret(%d)\n", ret);
        return HI_FAILURE;
    }
    ret = halBuffInit(&buffcfg);
    if (ret != HI_SUCCESS) {
        printf("manager halBuffInit failed! ret(%d)\n", ret);
        return HI_FAILURE;
    }
    return HI_SUCCESS;
}

void ImageMbufVideoSender::get_current_time_us(uint64_t &timeUs)
{
    struct timeval curTime;
    gettimeofday(&curTime, NULL);
    timeUs = (uint64_t)curTime.tv_sec * 1000000 + curTime.tv_usec;
}

void ImageMbufVideoSender::FillYuvAndSend(uint8_t *ptr, int32_t w, int32_t h)
{
    uintptr_t head;
    int32_t ret = GetMbuf(handle, head);
    if (ret != 0) {
        std::cout  << "GetMbuf head error"  << std::endl;
        return;
    }
    YuvImageInfo yuvImageInfo;
    yuvImageInfo.width = w;
    yuvImageInfo.height = h;
    //获取空闲Mbuf模块
    uintptr_t mbufTmp;
    ret = GetMbuf(handle, mbufTmp);
    if (ret != 0) {
        std::cout << "GetMbuf mbufTmp error" << std::endl;
        return;
    }
    //获取mbuff指针及长度
    uintptr_t outStream;
    uint64_t mbufMaxLen;
    uint64_t actualLen;
    ret = GetMbufPtrLength(mbufTmp, outStream, mbufMaxLen);
    if (ret != 0) {
        std::cout << "GetMbufPtrLength error" << std::endl;
        return;
    }
    size_t sizeInBytes = w * h * 3 / 2;
    actualLen = sizeInBytes;
    if (memcpy_s(reinterpret_cast<uint8_t *>(outStream), mbufMaxLen, ptr, actualLen) != 0) {
        std::cout << "outStream memcpy_s failed" << std::endl;
    }
    //设置mbuf长度
    ret = SetMbufPtr(mbufTmp, actualLen);
    if (ret != 0) {
        std::cout << "SetMbufPtr error" << std::endl;
        BufFree(mbufTmp);
        return;
    }
    //设置mbuf
    yuvImageInfo.mbuffer = mbufTmp;
    yuvImageInfo.length = static_cast<uint32_t>(actualLen);
    if (!PackCameraHead(yuvImageInfo, head)) {
        std::cout << "PackCameraHead error" << std::endl;
        return;
    }
    auto apData = dataSkeleton->cameraImageMbufEvent.Allocate();
    const uint32_t imageHeadType_ = 1U;
    const uint32_t imageYuvSemiplanarType_ = 1001U;
    const uint32_t mutiImageVersion_ = 0x1000U;
    apData->type.push_back(imageHeadType_);
    ret = AppendMbuf(head, yuvImageInfo.mbuffer);
    if (ret != 0) {
        std::cout << "AppendMbuf error" << ", ret" << ret << std::endl;
        return;
    }
    apData->type.push_back(imageYuvSemiplanarType_);
    apData->version = mutiImageVersion_;
    apData->seq = seq;
    apData->head = reinterpret_cast<rawBuffer *>(head);
    dataSkeleton->cameraImageMbufEvent.Send(std::move(apData));
    seq++;
    std::cout << "FillImageAndSend end -----" << std::endl;
    if (comPara.frequency != "") {
        int32_t freq = atoi(comPara.frequency.c_str());
        int32_t sleepTime = 1000000 / freq;
        usleep(sleepTime);
    } else {
        usleep(1000000 / 30); //30hz
    }
}

void ImageMbufVideoSender::save_yuv_file(FILE *const fd, hi_video_frame frame, uint32_t chanId)
{
    uint8_t *addr = (uint8_t *)frame.virt_addr[0];
    uint32_t imageSize = frame.width * frame.height * 3 / 2;
    int32_t ret = HI_SUCCESS;
    uint8_t *outImageBuf = nullptr;
    uint32_t outWidthStride = frame.width_stride[0];
    uint32_t outHeightStride = frame.height_stride[0];
    printf("[%s][%d] Chn %u, addr = %lx \n", __FUNCTION__, __LINE__, chanId, (uint64_t)(uintptr_t)frame.virt_addr[0]);
    printf("[%s][%d] Chn %u, Width = %u \n", __FUNCTION__, __LINE__, chanId, frame.width);
    printf("[%s][%d] Chn %u, Height = %u \n", __FUNCTION__, __LINE__, chanId, frame.height);
    printf("[%s][%d] Chn %u, PixelFormat = %d \n", __FUNCTION__, __LINE__, chanId, frame.pixel_format);
    printf("[%s][%d] Chn %u, OutWidthStride = %u \n", __FUNCTION__, __LINE__, chanId, frame.width_stride[0]);
    printf("[%s][%d] Chn %u, OutHeightStride = %u \n", __FUNCTION__, __LINE__, chanId, frame.height_stride[1]);
    printf("[%s][%d] Chn %u, fileName = %s \n", __FUNCTION__, __LINE__, chanId, g_input_file_name);
    if (g_run_mode == ACL_HOST) {
        // malloc host memory
        ret = aclrtMallocHost((void **)&outImageBuf, imageSize);
        if (ret != ACL_SUCCESS) {
            printf("[%s][%d] Chn %u malloc host memory %u failed, error code = %d \n", __FUNCTION__, __LINE__, chanId, imageSize, ret);
            return;
        }
    }
    if ((frame.width == outWidthStride) && (frame.height == outHeightStride)) {
        if (g_run_mode == ACL_HOST) {
            ret = aclrtMemcpy(outImageBuf, imageSize, addr, imageSize, ACL_MEMCPY_DEVICE_TO_HOST);
            if (ret != ACL_SUCCESS) {
                printf("[%s][%d] Chn %u Copy aclrtMemcpy %u from device to host failed, error code = %d \n", __FUNCTION__, __LINE__, chanId, imageSize, ret);
                return;
            }
            FillYuvAndSend(outImageBuf, frame.width, frame.height);
#ifdef SAVE_SENDER_FILE
            fwrite(outImageBuf, 1, imageSize, fd);
#endif
            aclrtFreeHost(outImageBuf);
        } else {
            FillYuvAndSend(addr, frame.width, frame.height);
#ifdef SAVE_SENDER_FILE
            fwrite(addr, imageSize, 1, fd);
#endif
        }
    } else {
        if (g_run_mode == ACL_HOST) {
            if (outImageBuf == NULL) {
                return;
            }
            for (uint32_t i = 0; i < frame.height; i++) {
                ret = aclrtMemcpy(outImageBuf + i * frame.width, frame.width, addr + i * outWidthStride, frame.width, ACL_MEMCPY_DEVICE_TO_HOST);
                if (ret != ACL_SUCCESS) {
                    printf("[%s][%d] Chn %u Copy aclrtMemcpy %u from device to host failed, error code = %d \n", __FUNCTION__, __LINE__, chanId, imageSize, ret);
                    aclrtFreeHost(outImageBuf);
                    return;
                }
            }
            for (uint32_t i = 0; i < frame.height / 2; i++) {
                ret = aclrtMemcpy(outImageBuf + i * frame.width + frame.width * frame.height, frame.width,
                                  addr + i * outWidthStride + outWidthStride * outHeightStride, frame.width, ACL_MEMCPY_DEVICE_TO_HOST);
                if (ret != ACL_SUCCESS) {
                    printf("[%s][%d] Chn %u Copy aclrtMemcpy %u from device to host failed, error code = %d \n", __FUNCTION__, __LINE__, chanId, imageSize, ret);
                    aclrtFreeHost(outImageBuf);
                    return;
                }
            }
            FillYuvAndSend(outImageBuf, frame.width, frame.height);
#ifdef SAVE_SENDER_FILE
            fwrite(outImageBuf, 1, imageSize, fd);
#endif
            aclrtFreeHost(outImageBuf);
        } else {
            uint8_t *outImageBuf = (uint8_t *)malloc(imageSize);
            if (outImageBuf == NULL) {
                printf("[%s][%d] Chn %u Malloc failed \n", __FUNCTION__, __LINE__, chanId);
                return;
            }
            for (uint32_t i = 0; i < frame.height; i++) {
                memcpy(outImageBuf + i * frame.width, addr + i * outWidthStride, frame.width);
            }
            for (uint32_t i = 0; i < frame.height / 2; i++) {
                memcpy(outImageBuf + i * frame.width + frame.width * frame.height,
                       addr + i * outWidthStride + outWidthStride * outHeightStride, frame.width);
            }
            FillYuvAndSend(outImageBuf, frame.width, frame.height);
#ifdef SAVE_SENDER_FILE
            fwrite(outImageBuf, 1, imageSize, fd);
#endif
            free(outImageBuf);
        }
    }
    return;
}

void ImageMbufVideoSender::save_rgb_file(FILE *const fd, hi_video_frame frame, uint32_t chanId)
{
    uint8_t *addr = (uint8_t *)frame.virt_addr[0];
    uint32_t imageSize = frame.width * frame.height * 3;
    int32_t ret = HI_SUCCESS;
    uint8_t *outImageBuf = nullptr;
    uint32_t outWidthStride = frame.width_stride[0];
    uint32_t outHeightStride = frame.height_stride[0];
    printf("[%s][%d] Chn %u, addr = %lx \n", __FUNCTION__, __LINE__, chanId, (uint64_t)(uintptr_t)frame.virt_addr[0]);
    printf("[%s][%d] Chn %u, Width = %d \n", __FUNCTION__, __LINE__, chanId, frame.width);
    printf("[%s][%d] Chn %u, Height = %d \n", __FUNCTION__, __LINE__, chanId, frame.height);
    printf("[%s][%d] Chn %u, PixelFormat = %d \n", __FUNCTION__, __LINE__, chanId, frame.pixel_format);
    printf("[%s][%d] Chn %u, OutWidthStride = %d \n", __FUNCTION__, __LINE__, chanId, frame.width_stride[0]);
    printf("[%s][%d] Chn %u, OutHeightStride = %d \n", __FUNCTION__, __LINE__, chanId, frame.height_stride[0]);
    if (g_run_mode == ACL_HOST) {
        // malloc host memory
        ret = aclrtMallocHost((void **)&outImageBuf, imageSize);
        if (ret != ACL_SUCCESS) {
            printf("[%s][%d] Chn %u malloc host memory %u failed, error code = %d \n", __FUNCTION__, __LINE__, chanId, imageSize, ret);
            return;
        }
    }
    if (((frame.width * 3) == outWidthStride) && (frame.height == outHeightStride)) {
        if (g_run_mode == ACL_HOST) {
            ret = aclrtMemcpy(outImageBuf, imageSize, addr, imageSize, ACL_MEMCPY_DEVICE_TO_HOST);
            if (ret != ACL_SUCCESS) {
                printf("[%s][%d] Chn %u Copy aclrtMemcpy %u from device to host failed, error code = %d \n", __FUNCTION__, __LINE__, chanId, imageSize, ret);
                return;
            }
            fwrite(outImageBuf, 1, imageSize, fd);
            aclrtFreeHost(outImageBuf);
        } else {
            fwrite(addr, imageSize, 1, fd);
        }
    } else {
        if (g_run_mode == ACL_HOST) {
            for (uint32_t i = 0; i < frame.height; i++) {
                ret = aclrtMemcpy(outImageBuf + i * frame.width * 3, frame.width * 3, addr + i * outWidthStride, frame.width * 3, ACL_MEMCPY_DEVICE_TO_HOST);
                if (ret != HI_SUCCESS) {
                    printf("[%s][%d] Chn %u Copy aclrtMemcpy %u from device to host failed, error code = %d \n", __FUNCTION__, __LINE__, chanId, imageSize, ret);
                    aclrtFreeHost(outImageBuf);
                    return;
                }
            }
            fwrite(outImageBuf, 1, imageSize, fd);
            aclrtFreeHost(outImageBuf);
        } else {
            uint8_t *outImageBuf = (uint8_t *)malloc(imageSize);
            if (outImageBuf == NULL) {
                printf("[%s][%d] Chn %u Malloc Fail \n", __FUNCTION__, __LINE__, chanId);
                return;
            }
            for (uint32_t i = 0; i < frame.height; i++) {
                memcpy(outImageBuf + i * frame.width * 3, addr + i * outWidthStride, frame.width * 3);
            }
            fwrite(outImageBuf, 1, imageSize, fd);
            free(outImageBuf);
        }
    }
    return;
}

int32_t ImageMbufVideoSender::vdec_create()
{
    int32_t ret = HI_SUCCESS;
    hi_vdec_chn_attr chnAttr[VDEC_MAX_CHN_NUM] {};
    hi_data_bit_width bitWidth = HI_DATA_BIT_WIDTH_8;
    if (g_in_bitwidth == 10) {
        bitWidth = HI_DATA_BIT_WIDTH_10;
    }
    for (uint32_t i = g_start_chn_num; i < g_start_chn_num + g_chn_num; i++) {
        if (g_in_format == 0) {
            chnAttr[i].type = HI_PT_H264;
        } else if (g_in_format == 1) {
            chnAttr[i].type = HI_PT_H265;
        }
        chnAttr[i].mode = HI_VDEC_SEND_MODE_FRAME;
        chnAttr[i].pic_width = g_in_width;
        chnAttr[i].pic_height = g_in_height;
        chnAttr[i].stream_buf_size = g_in_width * g_in_height * 3 / 2;
        chnAttr[i].frame_buf_cnt = g_ref_frame_num + g_display_frame_num + 1;
        hi_pic_buf_attr buf_attr{
            g_in_width, g_in_height, 0, bitWidth, HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420, HI_COMPRESS_MODE_NONE};
        chnAttr[i].frame_buf_size = hi_vdec_get_pic_buf_size(chnAttr[i].type, &buf_attr);
        chnAttr[i].video_attr.ref_frame_num = g_ref_frame_num;
        chnAttr[i].video_attr.temporal_mvp_en = HI_TRUE;
        chnAttr[i].video_attr.tmv_buf_size = hi_vdec_get_tmv_buf_size(chnAttr[i].type, g_in_width, g_in_height);
        ret = hi_mpi_vdec_create_chn(i, &chnAttr[i]);
        if (ret != HI_SUCCESS) {
            printf("[%s][%d] Chn %u hi_mpi_vdec_create_chn failed, ret = %x \n", __FUNCTION__, __LINE__, i, ret);
            return ret;
        }
        g_chan_create_state[i] = 1;
        hi_vdec_chn_param chnParam;
        ret = hi_mpi_vdec_get_chn_param(i, &chnParam);
        if (ret != HI_SUCCESS) {
            printf("[%s][%d] Chn %u hi_mpi_vdec_get_chn_param failed, ret = %x \n", __FUNCTION__, __LINE__, i, ret);
            return ret;
        }
        chnParam.video_param.dec_mode = HI_VIDEO_DEC_MODE_IPB;
        chnParam.video_param.compress_mode = HI_COMPRESS_MODE_HFBC;
        chnParam.video_param.video_format = HI_VIDEO_FORMAT_TILE_64x16;
        chnParam.display_frame_num = g_display_frame_num;
        if (g_output_order == 0) {
            chnParam.video_param.out_order = HI_VIDEO_OUT_ORDER_DISPLAY;
        } else {
            chnParam.video_param.out_order = HI_VIDEO_OUT_ORDER_DEC;
        }
        ret = hi_mpi_vdec_set_chn_param(i, &chnParam);
        if (ret != HI_SUCCESS) {
            printf("[%s][%d] Chn %u hi_mpi_vdec_set_chn_param failed, ret = %x \n", __FUNCTION__, __LINE__, i, ret);
            return ret;
        }
        ret = hi_mpi_vdec_start_recv_stream(i);
        if (ret != HI_SUCCESS) {
            printf("[%s][%d] Chn %u hi_mpi_vdec_start_recv_stream failed, ret = %x \n", __FUNCTION__, __LINE__, i, ret);
            return ret;
        }
    }
    return ret;
}

void ImageMbufVideoSender::vdec_reset_chn(uint32_t chanId)
{
    int32_t ret = HI_SUCCESS;
    hi_vdec_chn_status status{};
    ret = hi_mpi_vdec_stop_recv_stream(chanId);
    if (ret != HI_SUCCESS) {
        printf("[%s][%d] Chn %u hi_mpi_vdec_stop_recv_stream failed, ret = %x \n", __FUNCTION__, __LINE__, chanId, ret);
        return;
    }
    ret = hi_mpi_vdec_reset_chn(chanId);
    if (ret != HI_SUCCESS) {
        printf("[%s][%d] Chn %u, hi_mpi_vdec_reset_chn failed, ret = %x \n", __FUNCTION__, __LINE__, chanId, ret);
        return;
    }
    ret = hi_mpi_vdec_start_recv_stream(chanId);
    if (ret != HI_SUCCESS) {
        printf("[%s][%d] Chn %u, hi_mpi_vdec_start_recv_stream failed, ret = %x \n", __FUNCTION__, __LINE__, chanId, ret);
        return;
    }
    printf("[%s][%d] Chn %u reset chn success \n", __FUNCTION__, __LINE__, chanId);
    return;
}

void ImageMbufVideoSender::wait_vdec_end()
{
    int32_t ret = HI_SUCCESS;
    int32_t waitTimes;
    int32_t sleepTime = 10000;
    hi_vdec_chn_status status{};
    hi_vdec_chn_status pre_status{};
    for (uint32_t i = g_start_chn_num; i < g_start_chn_num + g_chn_num; i++) {
        if (g_vdec_send_thread[i] != 0) {
            ret = pthread_join(g_vdec_send_thread[i], NULL);
        }
        g_vdec_send_thread[i] = 0;
        waitTimes = 0;
        while (g_exit == 0) {
            ret = hi_mpi_vdec_query_status(i, &status);
            if (ret != HI_SUCCESS) {
                printf("[%s][%d] Chn %u, hi_mpi_vdec_query_status failed, ret = %x \n", __FUNCTION__, __LINE__, i, ret);
                break;
            }
            if (((status.left_stream_bytes == 0) && (status.left_decoded_frames == 0)) || (g_get_exit_state[i] == 1)) {
                break;
            }
            if (status.left_decoded_frames == pre_status.left_decoded_frames) {
                waitTimes += sleepTime;
            } else {
                waitTimes = 0;
            }
            pre_status = status;
            usleep(sleepTime);
            if (waitTimes >= 5000000) {
                vdec_reset_chn(i);
                break;
            }
        }
    }
    usleep(1000000);
    for (uint32_t i = g_start_chn_num; i < g_start_chn_num + g_chn_num; i++) {
        g_get_exit_state[i] = 1;
    }
    for (uint32_t i = g_start_chn_num; i < g_start_chn_num + g_chn_num; i++) {
        if (g_vdec_get_thread[i] != 0) {
            ret = pthread_join(g_vdec_get_thread[i], NULL);
        }
        g_vdec_get_thread[i] = 0;
    }
}

void ImageMbufVideoSender::vdec_destroy()
{
    int32_t ret = HI_SUCCESS;
    for (uint32_t i = g_start_chn_num; i < g_start_chn_num + g_chn_num; i++) {
        if (g_chan_create_state[i] == 1) {
            ret = hi_mpi_vdec_stop_recv_stream(i);
            if (ret != HI_SUCCESS) {
                printf("[%s][%d] Chn %u, hi_mpi_vdec_stop_recv_stream failed, ret = %x \n", __FUNCTION__, __LINE__, i, ret);
            }
            ret = hi_mpi_vdec_destroy_chn(i);
            if (ret != HI_SUCCESS) {
                printf("[%s][%d] Chn %u, hi_mpi_vdec_destroy_chn failed, ret = %x \n", __FUNCTION__, __LINE__, i, ret);
            }
            release_outbuffer(i);
        }
    }
}

int32_t ImageMbufVideoSender::create_send_stream_thread()
{
    int32_t ret = 0;
    uint32_t i = 0;
    g_vdec_send_thread[i] = 0;
    g_send_thread_id[i] = i;
    ret = pthread_create(&g_vdec_send_thread[i], 0, ImageMbufVideoSender::send_stream, this);
    if (ret != 0) {
        printf("[%s][%d] Chn %u create send stream thread failed, ret = %d \n", __FUNCTION__, __LINE__, i, ret);
        g_vdec_send_thread[i] = 0;
        return ret;
    }
    return ret;
}

int32_t ImageMbufVideoSender::create_get_pic_thread()
{
    int32_t ret;
    for (uint32_t i = g_start_chn_num; i < g_start_chn_num + g_chn_num; i++) {
        g_vdec_get_thread[i] = 0;
        g_get_thread_id[i] = i;
        ret = pthread_create(&g_vdec_get_thread[i], 0, ImageMbufVideoSender::get_pic, this);
        if (ret != 0) {
            printf("[%s][%d] Chn %u, create get pic thread failed, ret = %d \n", __FUNCTION__, __LINE__, i, ret);
            g_vdec_get_thread[i] = 0;
            return ret;
        }
    }
    return ret;
}

void *ImageMbufVideoSender::send_stream(void *arg)
{
    ImageMbufVideoSender *thiz = static_cast<ImageMbufVideoSender *>(arg);
    uint32_t sendFrameFailCnt = 0;
    prctl(PR_SET_NAME, "VdecSendStream", 0, 0, 0);
    uint32_t chanId = 0;
    aclError aclRet = aclrtSetCurrentContext(thiz->g_context);
    if (aclRet != ACL_SUCCESS) {
        printf("[%s][%d] Chn %u set current context failed, error code = %d \n", __FUNCTION__, __LINE__, chanId, aclRet);
        return (void *)(HI_FAILURE);
    }
    FILE *fpInputFile = NULL;
    fpInputFile = fopen(thiz->g_input_file_name, "rb");
    if (fpInputFile == NULL) {
        printf("[%s][%d] Chn %u Can not open file %s \n", __FUNCTION__, __LINE__, chanId, thiz->g_input_file_name);
        return (void *)(HI_FAILURE);
    }
    uint32_t fileSize = 0;
    fseek(fpInputFile, 0L, SEEK_END);
    fileSize = ftell(fpInputFile);
    fseek(fpInputFile, 0L, SEEK_SET);
    uint8_t *inputFileBuf = NULL;
    inputFileBuf = (uint8_t *)malloc(fileSize);
    if (inputFileBuf == NULL) {
        fclose(fpInputFile);
        printf("[%s][%d] Chn %u Malloc InputFile Buffer Fail \n", __FUNCTION__, __LINE__, chanId);
        return (void *)(HI_FAILURE);
    }
    uint32_t readLen = 0;
    readLen = fread(inputFileBuf, 1, fileSize, fpInputFile);
    if (readLen != fileSize) {
        fclose(fpInputFile);
        free(inputFileBuf);
        printf("[%s][%d] Chn %u Read InputFile Fail \n", __FUNCTION__, __LINE__, chanId);
        return (void *)(HI_FAILURE);
    }
    uint8_t *dataDev = HI_NULL;
    int32_t ret = HI_SUCCESS;
    if (thiz->g_run_mode == ACL_HOST) {
        ret = hi_mpi_dvpp_malloc(0, (void **)&dataDev, fileSize);
        if (ret != 0) {
            fclose(fpInputFile);
            free(inputFileBuf);
            printf("[%s][%d] Chn %u Malloc device memory %u failed \n", __FUNCTION__, __LINE__, chanId, fileSize);
            return (hi_void *)(HI_FAILURE);
        }
        ret = aclrtMemcpy(dataDev, fileSize, inputFileBuf, fileSize, ACL_MEMCPY_HOST_TO_DEVICE);
        if (ret != ACL_SUCCESS) {
            fclose(fpInputFile);
            free(inputFileBuf);
            hi_mpi_dvpp_free(dataDev);
            printf("[%s][%d] Chn %u Copy host memcpy to device failed, error code = %d. \n", __FUNCTION__, __LINE__, chanId, ret);
            return (hi_void *)(HI_FAILURE);
        }
    }
    uint32_t frameCount = 0;
    hi_payload_type type = (thiz->g_in_format == 0) ? HI_PT_H264 : HI_PT_H265;
    thiz->get_every_frame(chanId, inputFileBuf, &frameCount, fileSize, type, dataDev);
    void *outBuffer = NULL;
    uint32_t outBufferSize = 0;
    if ((thiz->g_out_format == 0) || (thiz->g_out_format == 1)) {
        outBufferSize = thiz->g_out_width_stride * thiz->g_out_height_stride * 3 / 2;
    } else if ((thiz->g_out_format == 2) || (thiz->g_out_format == 3)) {
        outBufferSize = thiz->g_out_width_stride * thiz->g_out_height_stride;
    }
    for (uint32_t i = 0; i < thiz->g_alloc_num; i++) {
        ret = hi_mpi_dvpp_malloc(0, &outBuffer, outBufferSize);
        if (ret != HI_SUCCESS) {
            fclose(fpInputFile);
            free(inputFileBuf);
            if (thiz->g_run_mode == ACL_HOST) {
                hi_mpi_dvpp_free(dataDev);
            }
            printf("[%s][%d] Chn %u hi_mpi_dvpp_malloc failed.\n", __FUNCTION__, __LINE__, chanId);
            return (void *)(HI_FAILURE);
        }
        thiz->g_out_buffer_pool[chanId].push_back(outBuffer);
    }
    thiz->delay_exec(thiz->g_start_time, thiz->g_delay_time);
    thiz->get_current_time_us(thiz->g_vdec_start_time[chanId]);
    hi_vdec_stream stream;
    hi_vdec_pic_info outPicInfo;
    uint32_t readCount = 0;
    hi_pixel_format outFormat = HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420;
    uint64_t currentSendTime = 0;
    uint64_t lastSendTime = 0;
    uint32_t circleTimes = 0;
    switch (thiz->g_out_format) {
    case 0:
        outFormat = HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420;
        break;
    case 1:
        outFormat = HI_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
        break;
    case 2:
        outFormat = HI_PIXEL_FORMAT_RGB_888;
        break;
    case 3:
        outFormat = HI_PIXEL_FORMAT_BGR_888;
        break;
    default:
        break;
    }
    int32_t timeOut = 1000;
    thiz->get_current_time_us(currentSendTime);
    while (1) {
        if (thiz->g_send_exit_state[chanId] == 1) {
            break;
        }
        stream.pts = currentSendTime + thiz->g_send_interval;
        stream.addr = thiz->g_frame_addr[chanId][readCount];
        stream.len = thiz->g_frame_len[chanId][readCount];
        stream.end_of_frame = HI_TRUE;
        stream.end_of_stream = HI_FALSE;
        outPicInfo.width = thiz->g_out_width;
        outPicInfo.height = thiz->g_out_height;
        outPicInfo.width_stride = thiz->g_out_width_stride;
        outPicInfo.height_stride = thiz->g_out_height_stride;
        outPicInfo.pixel_format = outFormat;
        if ((thiz->g_render == 0) || (readCount % thiz->g_render == 0)) {
            int32_t mallocCount = 0;
            int32_t tryTimes = 20000;
            while (thiz->g_send_exit_state[chanId] == 0) {
                mallocCount++;
                (void)pthread_mutex_lock(&thiz->g_out_buffer_pool_lock[chanId]);
                if (thiz->g_out_buffer_pool[chanId].empty() == false) {
                    outBuffer = thiz->g_out_buffer_pool[chanId].back();
                    thiz->g_out_buffer_pool[chanId].pop_back();
                    (void)pthread_mutex_unlock(&thiz->g_out_buffer_pool_lock[chanId]);
                    break;
                } else {
                    (void)pthread_mutex_unlock(&thiz->g_out_buffer_pool_lock[chanId]);
                    usleep(1000);
                }
                if (mallocCount >= tryTimes) {
                    printf("[%s][%d] Chn %u DvppMalloc From Pool Failed, Try again \n", __FUNCTION__, __LINE__, chanId);
                    mallocCount = 0;
                }
            }
            stream.need_display = HI_TRUE;
            outPicInfo.vir_addr = (uint64_t)outBuffer;
            outPicInfo.buffer_size = outBufferSize;
        } else {
            stream.need_display = HI_FALSE;
            outPicInfo.vir_addr = 0;
            outPicInfo.buffer_size = 0;
        }
        readCount = (readCount + 1) % frameCount;
        if (readCount == 0) {
            circleTimes++;
        }
        thiz->get_current_time_us(currentSendTime);
        if ((currentSendTime - lastSendTime) < thiz->g_send_interval) {
            usleep(thiz->g_send_interval - (currentSendTime - lastSendTime));
        }
        thiz->get_current_time_us(lastSendTime);
        do {
            sendFrameFailCnt++;
            ret = hi_mpi_vdec_send_stream(chanId, &stream, &outPicInfo, timeOut);
            if (sendFrameFailCnt > 30) {
                thiz->vdec_reset_chn(chanId);
                sendFrameFailCnt = 0;
                break;
            }
        } while (ret == HI_ERR_VDEC_BUF_FULL);
        if (ret != HI_SUCCESS) {
            printf("[%s][%d] Chn %u hi_mpi_vdec_send_stream failed, Error code = %x \n", __FUNCTION__, __LINE__, chanId, ret);
            break;
        } else {
            sendFrameFailCnt = 0;
            if ((thiz->g_send_times != 0) && (circleTimes >= thiz->g_send_times)) {
                break;
            }
        }
    }
    stream.addr = NULL;
    stream.len = 0;
    stream.end_of_frame = HI_FALSE;
    stream.end_of_stream = HI_TRUE;
    outPicInfo.vir_addr = 0;
    outPicInfo.buffer_size = 0;
    hi_mpi_vdec_send_stream(chanId, &stream, &outPicInfo, -1);
    fclose(fpInputFile);
    free(inputFileBuf);
    if (thiz->g_run_mode == ACL_HOST) {
        hi_mpi_dvpp_free(dataDev);
    }
    printf("[%s][%d] Chn %u send_stream Thread Exit \n", __FUNCTION__, __LINE__, chanId);
    return (hi_void *)HI_SUCCESS;
}

void *ImageMbufVideoSender::get_pic(void *arg)
{
    ImageMbufVideoSender *thiz = static_cast<ImageMbufVideoSender *>(arg);
    prctl(PR_SET_NAME, "VdecGetPic", 0, 0, 0);
    uint32_t chanId = 0;
    aclError aclRet = aclrtSetCurrentContext(thiz->g_context);
    if (aclRet != ACL_SUCCESS) {
        printf("[%s][%d] Chn %u set current context failed, error code = %d, \n", __FUNCTION__, __LINE__, chanId, aclRet);
        thiz->g_get_exit_state[chanId] = 1;
        return (void *)(HI_FAILURE);
    }
    int32_t ret = HI_SUCCESS;
    hi_video_frame_info frame;
    hi_vdec_stream stream;
    int32_t decResult = 0;
    void *outputBuffer = NULL;
    int32_t successCnt = 0;
    int32_t failCnt = 0;
    int32_t timeOut = 1000;
    int32_t writeFileCnt = 1;
    hi_vdec_supplement_info stSupplement{};
    while (1) {
        if (thiz->g_get_exit_state[chanId] == 1) {
            break;
        }
        ret = hi_mpi_vdec_get_frame(chanId, &frame, &stSupplement, &stream, timeOut);
        if (ret == HI_SUCCESS) {
            thiz->get_current_time_us(thiz->g_vdec_end_time[chanId]);
            outputBuffer = (void *) frame.v_frame.virt_addr[0];
            decResult = frame.v_frame.frame_flag;
            if (decResult == 0) {
                successCnt++;
                printf("[%s][%d] Chn %u GetFrame success, Decode success[%d] \n", __FUNCTION__, __LINE__, chanId, successCnt);
            } else if (decResult == 1) {
                failCnt++;
                printf("[%s][%d] Chn %u GetFrame success, Decode fail[%d] \n", __FUNCTION__, __LINE__, chanId, failCnt);
            } else if (decResult == 2) {
                printf("[%s][%d] Chn %u GetFrame success, No Picture \n", __FUNCTION__, __LINE__, chanId);
            } else if (decResult == 3) {
                failCnt++;
                printf("[%s][%d] Chn %u GetFrame success, RefFrame Num Error[%d] \n", __FUNCTION__, __LINE__, chanId, failCnt);
            } else if (decResult == 4) {
                failCnt++;
                printf("[%s][%d] Chn %u GetFrame success, RefFrame Size Error[%d] \n", __FUNCTION__, __LINE__, chanId, failCnt);
            }
            thiz->g_vdec_get_frame_cnt[chanId] = successCnt + failCnt;
            if ((thiz->g_is_write_file == 1) && (decResult == 0) &&
                    (outputBuffer != NULL) && (stream.need_display == HI_TRUE)) {
                FILE *fp = NULL;
                char saveFileName[256];
                ret = snprintf(saveFileName, sizeof(saveFileName), "%s_chn%u_%d", thiz->g_output_file_name, chanId, writeFileCnt);
                if (ret <= 0) {
                    printf("[%s][%d] Chn %u,snprintf_s fail \n", __FUNCTION__, __LINE__, chanId);
                    thiz->g_get_exit_state[chanId] = 1;
                    return (void *)(HI_FAILURE);
                }
                if ((frame.v_frame.pixel_format == HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420) ||
                        (frame.v_frame.pixel_format == HI_PIXEL_FORMAT_YVU_SEMIPLANAR_420)) {
                    thiz->save_yuv_file(thiz->fp_yuv, frame.v_frame, chanId);
                } else if ((frame.v_frame.pixel_format == HI_PIXEL_FORMAT_RGB_888) ||
                           (frame.v_frame.pixel_format == HI_PIXEL_FORMAT_BGR_888)) {
                    thiz->save_rgb_file(fp, frame.v_frame, chanId);
                }
                writeFileCnt++;
            }
            if (outputBuffer != NULL) {
                (void)pthread_mutex_lock(&thiz->g_out_buffer_pool_lock[chanId]);
                thiz->g_out_buffer_pool[chanId].push_back(outputBuffer);
                (void)pthread_mutex_unlock(&thiz->g_out_buffer_pool_lock[chanId]);
            }
            ret = hi_mpi_vdec_release_frame(chanId, &frame);
            if (ret != HI_SUCCESS) {
                printf("[%s][%d] Chn %u hi_mpi_vdec_release_frame Fail,Error Code = %x \n",
                       __FUNCTION__, __LINE__, chanId, ret);
            }
        } else {
            usleep(500);
        }
    }
    printf("[%s][%d] Chn %u get_pic Thread exit \n", __FUNCTION__, __LINE__, chanId);
    return (void *)HI_SUCCESS;
}

void ImageMbufVideoSender::get_every_frame(int32_t chanId, uint8_t *const inputFileBuf, uint32_t *const frameCount,
                                           uint32_t fileSize, hi_payload_type type, uint8_t *dataDev)
{
    int32_t i = 0;
    int32_t usedBytes = 0;
    int32_t readLen = 0;
    uint32_t count = 0;
    uint8_t *bufPointer = NULL;
    bool isFindStart = false;
    bool isFindEnd = false;
    while (1) {
        isFindStart = false;
        isFindEnd = false;
        bufPointer = inputFileBuf + usedBytes;
        readLen = fileSize - usedBytes;
        if (readLen <= 0) {
            break;
        }
        if (type == HI_PT_H264) {
            for (i = 0; i < readLen - 8; i++) {
                int32_t tmp = bufPointer[i + 3] & 0x1F;
                if ((bufPointer[i] == 0) && (bufPointer[i + 1] == 0) && (bufPointer[i + 2] == 1) &&
                        (((tmp == 0x5 || tmp == 0x1) && ((bufPointer[i + 4] & 0x80) == 0x80)) ||
                         (tmp == 20 && (bufPointer[i + 7] & 0x80) == 0x80))) {
                    isFindStart = true;
                    i += 8;
                    break;
                }
            }
            for (; i < readLen - 8; i++) {
                int32_t tmp = bufPointer[i + 3] & 0x1F;
                if ((bufPointer[i] == 0) && (bufPointer[i + 1] == 0) && (bufPointer[i + 2] == 1) &&
                        ((tmp == 15) || (tmp == 7) || (tmp == 8) || (tmp == 6) ||
                         ((tmp == 5 || tmp == 1) && ((bufPointer[i + 4] & 0x80) == 0x80)) ||
                         (tmp == 20 && (bufPointer[i + 7] & 0x80) == 0x80))) {
                    isFindEnd = true;
                    break;
                }
            }
            if (i > 0) {
                readLen = i;
            }
            if (isFindStart == false) {
                printf("Chn %d can not find h264 start code! readLen %d, usedBytes %d! \n", chanId, readLen, usedBytes);
            }
            if (isFindEnd == false) {
                readLen = i + 8;
            }
        } else if (type == HI_PT_H265) {
            bool isNewPic = false;
            for (i = 0; i < readLen - 6; i++) {
                uint32_t tmp = (bufPointer[i + 3] & 0x7E) >> 1;
                if ((bufPointer[i + 0] == 0) && (bufPointer[i + 1] == 0) && (bufPointer[i + 2] == 1) &&
                        (tmp >= 0 && tmp <= 21) && ((bufPointer[i + 5] & 0x80) == 0x80)) {
                    isNewPic = true;
                }
                if (isNewPic == true) {
                    isFindStart = true;
                    i += 6;
                    break;
                }
            }
            for (; i < readLen - 6; i++) {
                uint32_t tmp = (bufPointer[i + 3] & 0x7E) >> 1;
                isNewPic = ((bufPointer[i + 0] == 0) && (bufPointer[i + 1] == 0) && (bufPointer[i + 2] == 1) &&
                            ((tmp == 32) || (tmp == 33) || (tmp == 34) || (tmp == 39) || (tmp == 40) ||
                             ((tmp >= 0 && tmp <= 21) && (bufPointer[i + 5] & 0x80) == 0x80)));
                if (isNewPic == true) {
                    isFindEnd = true;
                    break;
                }
            }
            if (i > 0) {
                readLen = i;
            }
            if (isFindStart == false) {
                printf("Chn %d can not find h265 start code! readLen %d, usedBytes %d! \n", chanId, readLen, usedBytes);
            }
            if (isFindEnd == false) {
                readLen = i + 6;
            }
        }
        if (g_run_mode == ACL_HOST) {
            g_frame_addr[chanId][count] = (bufPointer - inputFileBuf) + dataDev;
        } else {
            g_frame_addr[chanId][count] = bufPointer;
        }
        g_frame_len[chanId][count] = readLen;
        count++;
        usedBytes = usedBytes + readLen;
    }
    *frameCount = count;
}

void ImageMbufVideoSender::delay_exec(uint64_t execTime, int32_t seconds)
{
    struct timeval currentTime;
    uint64_t tmpCurtime = 0;
    uint64_t secondToUs = 1000000;
    gettimeofday(&currentTime, NULL);
    tmpCurtime = currentTime.tv_sec * secondToUs + currentTime.tv_usec;
    uint64_t nextExecTime = execTime + seconds * secondToUs;
    while (tmpCurtime < nextExecTime) {
        usleep(500);
        gettimeofday(&currentTime, NULL);
        tmpCurtime = currentTime.tv_sec * secondToUs + currentTime.tv_usec;
    }
    return;
}

void ImageMbufVideoSender::show_decode_performance()
{
    double averFrameRate = 0;
    uint32_t chnNum = 0;
    uint64_t secondToUs = 1000000;
    for (uint32_t i = g_start_chn_num; i < g_start_chn_num + g_chn_num; i++) {
        uint64_t diffTime = g_vdec_end_time[i] - g_vdec_start_time[i];
        if (diffTime == 0) {
            continue;
        }
        printf("\033[0;33m -------------------------------------------------------- \033[0;39m\n");
        double actualFrameRate = ((double)g_vdec_get_frame_cnt[i] * secondToUs) / diffTime;
        printf("\033[0;33m chnId %u, actualFrameRate %.1f, SendFrameCnt %lu, DiffTime %lu \033[0;39m\n",
               i, actualFrameRate, g_vdec_get_frame_cnt[i], diffTime);
        printf("\033[0;33m -------------------------------------------------------- \033[0;39m\n");
        averFrameRate += actualFrameRate;
        chnNum++;
    }
    averFrameRate = averFrameRate / chnNum;
    printf("\033[0;33m ChanNum = %u, Average FrameRate = %.1f fps \033[0;39m\n", chnNum, averFrameRate);
    return;
}

int32_t ImageMbufVideoSender::get_option(int32_t argc, char **argv)
{
    int32_t ret = HI_SUCCESS;
    while (1) {
        int32_t optionIndex = 0;
        option longOptions[] = {
            {"img_width", 1, 0, 'a'},
            {"img_height", 1, 0, 'b'},
            {"in_image_file", 1, 0, 'c'},
            {"in_format", 1, 0, 'd'},
            {"in_bitwidth", 1, 0, 'e'},
            {"out_width", 1, 0, 'f'},
            {"out_height", 1, 0, 'g'},
            {"out_image_file", 1, 0, 'h'},
            {"out_format", 1, 0, 'i'},
            {"width_stride", 1, 0, 'j'},
            {"height_stride", 1, 0, 'k'},
            {"write_file", 1, 0, 'l'},
            {"chn_num", 1, 0, 'm'},
            {"ref_frame_num", 1, 0, 'n'},
            {"dis_frame_num", 1, 0, 'o'},
            {"output_order", 1, 0, 'p'},
            {"send_times", 1, 0, 'q'},
            {"send_interval", 1, 0, 'r'},
            {"delay_time", 1, 0, 's'},
            {"alloc_num", 1, 0, 't'},
            {"start_chn", 1, 0, 'w'},
            {"render", 1, 0, 'v'}
        };
        int32_t parameter = getopt_long(argc, argv,
                                        "a:b:c:d:e:f:g:h:i:j:k:l:m:n:o:p:q:r:s:t:w:v:", longOptions, &optionIndex);
        if (parameter == -1) {
            break;
        }
        switch (parameter) {
        case 'a':
            g_in_width = atoi(optarg);
            break;
        case 'b':
            g_in_height = atoi(optarg);
            break;
        case 'c':
            strcpy(g_input_file_name, optarg);
            break;
        case 'd':
            g_in_format = atoi(optarg);
            break;
        case 'e':
            g_in_bitwidth = atoi(optarg);
            break;
        case 'f':
            g_out_width = atoi(optarg);
            break;
        case 'g':
            g_out_height = atoi(optarg);
            break;
        case 'h':
            strcpy(g_output_file_name, optarg);
            break;
        case 'i':
            g_out_format = atoi(optarg);
            break;
        case 'j':
            g_out_width_stride = atoi(optarg);
            break;
        case 'k':
            g_out_height_stride = atoi(optarg);
            break;
        case 'l':
            g_is_write_file = atoi(optarg);
            break;
        case 'm':
            g_chn_num = atoi(optarg);
            break;
        case 'n':
            g_ref_frame_num = atoi(optarg);
            break;
        case 'o':
            g_display_frame_num = atoi(optarg);
            break;
        case 'p':
            g_output_order = atoi(optarg);
            break;
        case 'q':
            g_send_times = atoi(optarg);
            break;
        case 'r':
            g_send_interval = atoi(optarg);
            break;
        case 's':
            g_delay_time = atoi(optarg);
            break;
        case 't':
            g_alloc_num = atoi(optarg);
            break;
        case 'w':
            g_start_chn_num = atoi(optarg);
            break;
        case 'v':
            g_render = atoi(optarg);
            break;
        default:
            printf("this is default! \n");
            break;
        }
        if (ret != HI_SUCCESS) {
            return ret;
        }
    }
    return ret;
}

int32_t ImageMbufVideoSender::check_option()
{
    if ((g_in_width > 4096) || (g_in_width < 128)) {
        printf("[%s][%d] input file width is invalid, width = %u \n", __FUNCTION__, __LINE__, g_in_width);
        return HI_FAILURE;
    }
    if ((g_in_height > 4096) || (g_in_height < 128)) {
        printf("[%s][%d] input file height is invalid, height = %u \n", __FUNCTION__, __LINE__, g_in_height);
        return HI_FAILURE;
    }
    if ((g_in_format != 0) && (g_in_format != 1)) {
        printf("[%s][%d] input format is invalid, format = %u \n", __FUNCTION__, __LINE__, g_in_format);
        return HI_FAILURE;
    }
    if ((g_in_bitwidth != 8) && (g_in_bitwidth != 10)) {
        printf("[%s][%d] input bitwidth is invalid, bitwidth = %u \n", __FUNCTION__, __LINE__, g_in_bitwidth);
        return HI_FAILURE;
    }
    if ((g_out_width != 0) && ((g_out_width > 4096) || (g_out_width < 10))) {
        printf("[%s][%d] output width is invalid, width = %u \n", __FUNCTION__, __LINE__, g_out_width);
        return HI_FAILURE;
    }
    if ((g_out_height != 0) && ((g_out_height > 4096) || (g_out_height < 6))) {
        printf("[%s][%d] output height is invalid, height = %u \n", __FUNCTION__, __LINE__, g_out_height);
        return HI_FAILURE;
    }
    if (g_out_format > 3) {
        printf("[%s][%d] output format is invalid, format = %u \n", __FUNCTION__, __LINE__, g_out_format);
        return HI_FAILURE;
    }
    if ((g_out_width_stride % 16 != 0) || (g_out_width_stride < g_out_width) || (g_out_width_stride < 32)) {
        printf("[%s][%d] output width stride is invalid, width stride = %u \n", __FUNCTION__, __LINE__, g_out_width_stride);
        return HI_FAILURE;
    }
    if (((g_out_format == 2) || (g_out_format == 3)) && (g_out_width_stride < g_out_width * 3)) {
        printf("[%s][%d] output width stride is invalid, width stride = %u \n", __FUNCTION__, __LINE__, g_out_width_stride);
        return HI_FAILURE;
    }
    if (((g_out_height_stride % 2 != 0) && ((g_out_format == 0) || (g_out_format == 1))) ||
            (g_out_height_stride < g_out_height)) {
        printf("[%s][%d] output height stride is invalid, height stride = %u \n", __FUNCTION__, __LINE__, g_out_height_stride);
        return HI_FAILURE;
    }
    if (g_is_write_file > 1) {
        printf("[%s][%d] write file parameter is invalid, isWriteFile = %u \n", __FUNCTION__, __LINE__, g_is_write_file);
        return HI_FAILURE;
    }
    if ((g_chn_num > 96) || (g_chn_num < 1)) {
        printf("[%s][%d] chan num is invalid, chan num = %u \n", __FUNCTION__, __LINE__, g_chn_num);
        return HI_FAILURE;
    }
    if (g_ref_frame_num > 16) {
        printf("[%s][%d] RefFrame num is invalid, RefFrame num = %u \n", __FUNCTION__, __LINE__, g_ref_frame_num);
        return HI_FAILURE;
    }
    if (g_display_frame_num > 16) {
        printf("[%s][%d] DisplayFrame num is invalid, DisplayFrame num = %u \n", __FUNCTION__, __LINE__, g_display_frame_num);
        return HI_FAILURE;
    }
    if (g_output_order > 2) {
        printf("[%s][%d] output order is invalid, output order = %u \n", __FUNCTION__, __LINE__, g_output_order);
        return HI_FAILURE;
    }
    if (g_start_chn_num + g_chn_num >= VDEC_MAX_CHN_NUM) {
        printf("[%s][%d] start chan num is invalid, start chan num = %u \n", __FUNCTION__, __LINE__, g_start_chn_num);
        return HI_FAILURE;
    }
    return HI_SUCCESS;
}

void ImageMbufVideoSender::print_parameter()
{
    printf("\n/****************************Vdec Parameter****************************/\n");
    printf("InputFileName: %s \n", g_input_file_name);
    printf("OutputFileName: %s \n", g_output_file_name);
    printf("Width: %u \n", g_in_width);
    printf("Height: %u \n", g_in_height);
    printf("InFormat: %u \n", g_in_format);
    printf("Bitwidth: %u \n", g_in_bitwidth);
    printf("OutWidth: %u \n", g_out_width);
    printf("OutHeight: %u \n", g_out_height);
    printf("OutFormat: %u \n", g_out_format);
    printf("OutWidthStride: %u \n", g_out_width_stride);
    printf("OutHeightStride: %u \n", g_out_height_stride);
    printf("ChnNum: %u \n", g_chn_num);
    printf("RefFrameNum: %u \n", g_ref_frame_num);
    printf("DisplayFrameNum: %u \n", g_display_frame_num);
    printf("OutPutOrder: %u \n", g_output_order);
    printf("SendTimes: %u \n", g_send_times);
    printf("SendInterval: %u \n", g_send_interval);
    printf("DelayTime: %u \n", g_delay_time);
    printf("AllocNum: %u \n", g_alloc_num);
    printf("StartChnNum: %u \n", g_start_chn_num);
    printf("Render: %u \n", g_render);
    printf("/**********************************************************************/\n");
}

void ImageMbufVideoSender::vdec_handle_signal(int32_t signo)
{
    for (int32_t i = g_start_chn_num; i < g_start_chn_num + g_chn_num; i++) {
        g_send_exit_state[i] = 1;
    }
    g_exit = 1;
    printf("Program Exit Abnormally! \n");
}

void ImageMbufVideoSender::init_outbuffer_lock()
{
    for (uint32_t i = g_start_chn_num; i < g_start_chn_num + g_chn_num; i++) {
        pthread_mutex_init(&g_out_buffer_pool_lock[i], NULL);
    }
}

void ImageMbufVideoSender::destroy_outbuffer_lock()
{
    for (uint32_t i = g_start_chn_num; i < g_start_chn_num + g_chn_num; i++) {
        pthread_mutex_destroy(&g_out_buffer_pool_lock[i]);
    }
}

void ImageMbufVideoSender::release_outbuffer(uint32_t chanId)
{
    void *outBuffer = NULL;
    while (g_out_buffer_pool[chanId].empty() == false) {
        outBuffer = g_out_buffer_pool[chanId].back();
        g_out_buffer_pool[chanId].pop_back();
        hi_mpi_dvpp_free(outBuffer);
    }
}

void ImageMbufVideoSender::get_start_time()
{
    struct timeval currentTime;
    gettimeofday(&currentTime, NULL);
    g_start_time = currentTime.tv_sec * 1000000 + currentTime.tv_usec;
}

int32_t ImageMbufVideoSender::hi_dvpp_init()
{
    int32_t s32Ret = ACL_SUCCESS;
    aclError aclRet = aclInit(NULL);
    if ((aclRet != ACL_SUCCESS) && (aclRet != 100002)) {
        printf("[%s][%d] aclInit failed, error code = %d. \n", __FUNCTION__, __LINE__, aclRet);
        return HI_FAILURE;
    }
    printf("[%s][%d] aclInit success \n", __FUNCTION__, __LINE__);
    aclRet = aclrtSetDevice(0);
    if (aclRet != ACL_SUCCESS) {
        printf("[%s][%d] aclrtSetDevice 0 failed, error code = %d \n", __FUNCTION__, __LINE__, aclRet);
        aclFinalize();
        return HI_FAILURE;
    }
    printf("[%s][%d] aclrtSetDevice 0 success \n", __FUNCTION__, __LINE__);
    aclRet = aclrtCreateContext(&g_context, 0);
    if (aclRet != ACL_SUCCESS) {
        printf("[%s][%d] aclrtCreateContext failed, error code = %d \n", __FUNCTION__, __LINE__, aclRet);
        aclrtResetDevice(0);
        aclFinalize();
        return HI_FAILURE;
    }
    printf("[%s][%d] aclrtCreateContext success \n", __FUNCTION__, __LINE__);
    int32_t ret = hi_mpi_sys_init();
    if (ret != HI_SUCCESS) {
        printf("[%s][%d] hi_mpi_sys_init failed, error code = %x \n", __FUNCTION__, __LINE__, ret);
        aclrtDestroyContext(g_context);
        aclrtResetDevice(0);
        aclFinalize();
        return HI_FAILURE;
    }
    aclRet = aclrtGetRunMode(&g_run_mode);
    if (aclRet != HI_SUCCESS) {
        printf("[%s][%d] aclrtGetRunMode failed, error code = %x. \n", __FUNCTION__, __LINE__, aclRet);
        hi_mpi_sys_exit();
        aclrtDestroyContext(g_context);
        aclrtResetDevice(0);
        aclFinalize();
        return HI_FAILURE;
    }
    printf("[%s][%d] Dvpp system init success \n", __FUNCTION__, __LINE__);
    return HI_SUCCESS;
}

void ImageMbufVideoSender::hi_dvpp_deinit()
{
    int32_t ret = hi_mpi_sys_exit();
    if (ret != HI_SUCCESS) {
        printf("[%s][%d] hi_mpi_sys_exit failed, error code = %x. \n", __FUNCTION__, __LINE__, ret);
    }
    aclError aclRet = aclrtDestroyContext(g_context);
    if (aclRet != ACL_SUCCESS) {
        printf("[%s][%d] aclrtDestroyContext failed, error code = %d. \n", __FUNCTION__, __LINE__, aclRet);
    }
    aclRet = aclrtResetDevice(0);
    if (aclRet != ACL_SUCCESS) {
        printf("[%s][%d] aclrtResetDevice 0 failed, error code = %d. \n", __FUNCTION__, __LINE__, aclRet);
    }
    aclRet = aclFinalize();
    if ((aclRet != ACL_SUCCESS) && (aclRet != 100037)) {
        printf("[%s][%d] aclFinalize failed, error code = %d. \n", __FUNCTION__, __LINE__, aclRet);
    }
    printf("[%s][%d] Dvpp system exit success \n", __FUNCTION__, __LINE__);
}

void ImageMbufVideoSender::stop_send_stream_thread()
{
    for (uint32_t i = g_start_chn_num; i < g_start_chn_num + g_chn_num; i++) {
        g_send_exit_state[i] = 1;
    }
    g_exit = 1;
}

void ImageMbufVideoSender::stop_get_pic_thread()
{
    for (uint32_t i = g_start_chn_num; i < g_start_chn_num + g_chn_num; i++) {
        g_get_exit_state[i] = 1;
        g_send_exit_state[i] = 1;
    }
    g_exit = 1;
}

